package net.jgrm.common.util;

import java.security.SecureRandom;
import java.util.Random;
import java.util.UUID;

/**
 * 随机数工具类
 *
 * @author service-common
 */
public class RandomUtils {

    private static final String UPPER_CASE_LETTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    private static final String LOWER_CASE_LETTERS = "abcdefghijklmnopqrstuvwxyz";
    private static final String NUMBERS = "0123456789";
    private static final String SPECIAL_CHARS = "!@#$%^&*()_+-=[]{}|;:,.<>?";

    private static final Random RANDOM = new SecureRandom();

    /**
     * 私有构造函数
     */
    private RandomUtils() {
        // 工具类不允许实例化
    }

    /**
     * 生成指定长度的随机数字字符串
     *
     * @param length 长度
     * @return 随机数字字符串
     */
    public static String randomNumbers(int length) {
        return randomString(NUMBERS, length);
    }

    /**
     * 生成指定长度的随机字母字符串（大小写混合）
     *
     * @param length 长度
     * @return 随机字母字符串
     */
    public static String randomLetters(int length) {
        return randomString(UPPER_CASE_LETTERS + LOWER_CASE_LETTERS, length);
    }

    /**
     * 生成指定长度的随机字母数字字符串
     *
     * @param length 长度
     * @return 随机字母数字字符串
     */
    public static String randomAlphanumeric(int length) {
        return randomString(UPPER_CASE_LETTERS + LOWER_CASE_LETTERS + NUMBERS, length);
    }

    /**
     * 生成指定长度的随机字符串（包含字母、数字、特殊字符）
     *
     * @param length 长度
     * @return 随机字符串
     */
    public static String randomString(int length) {
        return randomString(UPPER_CASE_LETTERS + LOWER_CASE_LETTERS + NUMBERS + SPECIAL_CHARS, length);
    }

    /**
     * 从指定字符集中生成指定长度的随机字符串
     *
     * @param chars  字符集
     * @param length 长度
     * @return 随机字符串
     */
    public static String randomString(String chars, int length) {
        if (StringUtils.isBlank(chars) || length <= 0) {
            return "";
        }

        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < length; i++) {
            int index = RANDOM.nextInt(chars.length());
            sb.append(chars.charAt(index));
        }
        return sb.toString();
    }

    /**
     * 生成指定范围内的随机整数
     *
     * @param min 最小值（包含）
     * @param max 最大值（不包含）
     * @return 随机整数
     */
    public static int randomInt(int min, int max) {
        if (min >= max) {
            throw new IllegalArgumentException("min must be less than max");
        }
        return RANDOM.nextInt(max - min) + min;
    }

    /**
     * 生成指定范围内的随机长整数
     *
     * @param min 最小值（包含）
     * @param max 最大值（不包含）
     * @return 随机长整数
     */
    public static long randomLong(long min, long max) {
        if (min >= max) {
            throw new IllegalArgumentException("min must be less than max");
        }
        return RANDOM.nextLong() % (max - min) + min;
    }

    /**
     * 生成随机布尔值
     *
     * @return 随机布尔值
     */
    public static boolean randomBoolean() {
        return RANDOM.nextBoolean();
    }

    /**
     * 生成随机UUID
     *
     * @return UUID字符串
     */
    public static String randomUUID() {
        return UUID.randomUUID().toString();
    }

    /**
     * 生成不带横线的随机UUID
     *
     * @return UUID字符串（无横线）
     */
    public static String randomUUIDWithoutDash() {
        return UUID.randomUUID().toString().replace("-", "");
    }

    /**
     * 生成指定长度的随机密码
     * 包含大小写字母、数字和特殊字符
     *
     * @param length 密码长度
     * @return 随机密码
     */
    public static String randomPassword(int length) {
        if (length < 4) {
            throw new IllegalArgumentException("Password length must be at least 4");
        }

        StringBuilder password = new StringBuilder();

        // 确保至少包含一个大写字母、小写字母、数字和特殊字符
        password.append(randomString(UPPER_CASE_LETTERS, 1));
        password.append(randomString(LOWER_CASE_LETTERS, 1));
        password.append(randomString(NUMBERS, 1));
        password.append(randomString(SPECIAL_CHARS, 1));

        // 剩余长度随机生成
        String allChars = UPPER_CASE_LETTERS + LOWER_CASE_LETTERS + NUMBERS + SPECIAL_CHARS;
        password.append(randomString(allChars, length - 4));

        // 打乱字符顺序
        return shuffleString(password.toString());
    }

    /**
     * 打乱字符串中字符的顺序
     *
     * @param str 原字符串
     * @return 打乱后的字符串
     */
    public static String shuffleString(String str) {
        if (StringUtils.isBlank(str)) {
            return str;
        }

        char[] chars = str.toCharArray();
        for (int i = 0; i < chars.length; i++) {
            int randomIndex = RANDOM.nextInt(chars.length);
            char temp = chars[i];
            chars[i] = chars[randomIndex];
            chars[randomIndex] = temp;
        }
        return new String(chars);
    }

    /**
     * 生成6位数字验证码
     *
     * @return 6位数字验证码
     */
    public static String randomVerificationCode() {
        return randomNumbers(6);
    }

    /**
     * 生成指定长度的数字验证码
     *
     * @param length 验证码长度
     * @return 数字验证码
     */
    public static String randomVerificationCode(int length) {
        return randomNumbers(length);
    }
}